// Copyright (c) 2014-present, b3log.org
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package output

import (
	"bufio"
	"chainmaker.org/chainmaker/smarteditor/common"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/jinzhu/gorm"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"time"

	"chainmaker.org/chainmaker/smarteditor/conf"
	"chainmaker.org/chainmaker/smarteditor/file"
	"chainmaker.org/chainmaker/smarteditor/global"
	"chainmaker.org/chainmaker/smarteditor/i18n"
	"chainmaker.org/chainmaker/smarteditor/session"
	"chainmaker.org/chainmaker/smarteditor/util"
	"github.com/88250/gulu"
	"github.com/tjfoc/gmsm/sm3"
	"golang.org/x/sync/singleflight"
)

const WindowsSuffix = ".exe"

var (
	crossBuildSg singleflight.Group
)

type buildResponse struct {
	File string `json:"file"`
}

// CrossCompilationHandler handles request of cross compilation.
func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {

	uid, err := session.GetUidFromSession(r)
	if err != nil {
		log.Errorf("CrossCompilationHandler Forbidden. url:%s,uid:%s, err:%v", r.URL, uid, err)
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	result := gulu.Ret.NewResult()
	defer gulu.Ret.RetResult(w, r, result)

	var args map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		log.Errorf("CrossCompilationHandler decode parameter failed. url:%s, err:%v", r.URL, err)
		result.Code = -1
		return
	}
	sid := args["sid"].(string)
	path := args["path"].(string)
	platform := args["platform"].(string)
	contracttype := args["contract_type"].(string)
	//contracttype := "EVM"
	//contracttype := "Go"

	log.Errorf("build -----1111111----, sid:%s, path:%s  platform:%s, contracttype:%s", sid, path, platform, contracttype)

	if sid == "" || path == "" || platform == "" || contracttype == "" {
		http.Error(w, "parameter error", http.StatusBadRequest)
		return
	}
	if !file.HasAccessPermission(uid, path) {
		http.Error(w, "not permission", http.StatusUnauthorized)
		return
	}

	workspace := conf.GetUserWorkspace(uid)

	if !util.IsContractRootDirectory(workspace, filepath.Dir(path)) {
		log.Errorf("cross compile handler, file path is not contract root path, don't need build. uid:%s, workspace:%s, file path:%s", uid, sid, path)
		result.Code = -1
		return
	}

	curDirectory := filepath.Dir(path)
	log.Errorf("evm build -----111111. curDirectory:%s, path:%s", curDirectory, path)

	if strings.EqualFold(contracttype, "EVM") {
		//path = "/data/wide/workspaces/admin/src/Hello/"  变成 path = "/data/wide/workspaces/admin/src/Hello/Hello.sol" //测试值，要删除=================================
		lastDir := filepath.Base(strings.TrimSuffix(path, "/"))
		path = path + lastDir + ".sol"
		user := conf.GetUser(uid)
		filename := filepath.Base(path)
		fmt.Println("文件名:", filename) // 输出: file.txt

		extension := filepath.Ext(filename)
		fmt.Println("扩展名:", extension) // 输出: .txt
		if strings.EqualFold(extension, "sol") {
			log.Errorf("扩展名错误. 扩展名为:%s", extension)
			result.Code = -1
			result.Msg = "扩展名错误"
			return
		}
		nameNoExt := filename[:len(filename)-len(extension)]
		abiFileName := nameNoExt + ".abi"
		binFileName := nameNoExt + ".bin"
		//solc --bin --abi -o <output_directory> <your_smart_contract.sol>
		var goBuildArgs []string
		goBuildArgs = append(goBuildArgs, "--overwrite", "--bin", "--abi", "-o out", filename)
		cmd := exec.Command(runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/solc", goBuildArgs...)
		cmd.Dir = curDirectory

		//goos := strings.Split(platform, "_")[0]
		//goarch := strings.Split(platform, "_")[1]
		//
		////非测试环境执行环境变量设置
		//if global.TestnetEnv != true {
		//	setCmdEnvWithOsAndArchAndGoRoot(cmd, uid, goos, goarch, os.Getenv("GOPATH"), runtime.GOROOT()+RealSdkGoRootSuffix)
		//}

		stdout, stderr, err := util.OpenStdOutAndStdErr(cmd)
		if err != nil {
			log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err)
			result.Code = -1
			result.Msg = err.Error()
			return
		}

		err = writeMessageToWebSocket(sid, uid, "solc", "正在编译合约")
		if err != nil {
			log.Errorf("CrossCompilationHandler write start build message to websocket failed.uid:%s, err :%s", uid, err)
			result.Code = -1
			result.Msg = err.Error()
			return
		}

		if err := cmd.Start(); nil != err {
			log.Errorf("CrossCompilationHandler start cmd faild. err:%s", err)
			result.Code = -1
			result.Msg = err.Error()
			return
		}
		log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
		WaitCmdRunSuccessEVM(rand.Int(), cmd, stdout, stderr, user.Locale, binFileName, filepath.Base(curDirectory), curDirectory, sid)

		//生成脚手架
		cmd1 := exec.Command("/usr/bin/sh", "-c", runtime.GOROOT()+RealSdkGoRootSuffix+"/web3j/bin/web3j.sh generate solidity --abiFile='"+filepath.Join(curDirectory, " out", abiFileName)+"' --outputDir=./ --package=framework")
		cmd1.Dir = curDirectory

		stdout1, stderr1, err1 := util.OpenStdOutAndStdErr(cmd1)
		if err1 != nil {
			log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err1)
			result.Code = -1
			result.Msg = err1.Error()
			return
		}

		err = writeMessageToWebSocket(sid, uid, "web3j", "正在生成java脚手架文件")
		if err != nil {
			log.Errorf("CrossCompilationHandler write start build message to websocket failed.uid:%s, err :%s", uid, err)
			result.Code = -1
			result.Msg = err.Error()
			return
		}

		if err := cmd1.Start(); nil != err {
			log.Errorf("CrossCompilationHandler start cmd faild. err:%s", err)
			result.Code = -1
			result.Msg = err.Error()
			return
		}
		log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd1.Path, cmd1.Args, cmd1.Env, cmd1.Dir)
		WaitCmdRunSuccessEVM(rand.Int(), cmd1, stdout1, stderr1, user.Locale, binFileName, filepath.Base(curDirectory), curDirectory, sid)

		file7z, err := generateBuildAndDeployFileEvm(curDirectory, workspace, nameNoExt, uid)
		if err != nil {
			log.Errorf("CrossCompilationHandler generate build file fail. err:%s", err)
			result.Code = -1
			result.Msg = err.Error()
			return
		}

		result.Data = buildResponse{File: file7z}
		return
	}

	is210, checkErr := util.CheckContractIs210(curDirectory)
	if checkErr != nil {
		log.Errorf("CheckContractIs210 %s failed %s ", curDirectory, checkErr.Error())
	}
	if is210 {
		result.Code = -1
		// result.Msg = path + " is contract 210,not supported"
		sendBuildErrorMessageToWs(uid, sid, path+" 检测到合约版本为v2.1.0+，请将IDE的长安链版本切换至v2.1.0+再进行操作")
		return
	}
	if !gulu.File.IsExist(filepath.Join(curDirectory, "go.mod")) {
		output, err := util.RunGoModInit(uid, curDirectory, workspace, os.Getenv("GOPATH"), os.Getenv("GOROOT")+RealSdkGoRootSuffix, conf.Docker)
		if err != nil {
			sendBuildErrorMessageToWs(uid, sid, output)
			log.Errorf("CrossCompilationHandler init go mod fail. output:%s, err:%v", output, err)
			result.Code = -1
			return
		}
		//执行go get获取指定依赖
		//output, err = util.RunGoGet(uid, curDirectory, workspace, conf.Docker)
		//if err != nil {
		//	sendBuildErrorMessageToWs(uid, sid, output)
		//	log.Errorf("build handler go get fail. output:%s, err:%v", output, err)
		//	result.Code = -1
		//	return
		//}
	}
	output, err := util.RunGoModTidyInDirectoryDocker(curDirectory, conf.Docker, os.Getenv("GOPATH"), os.Getenv("GOROOT")+RealSdkGoRootSuffix)
	if err != nil {
		sendBuildErrorMessageToWs(uid, sid, output)
		log.Errorf("CrossCompilationHandler init go tidy fail. output:%s, err:%v", output, err)
		result.Code = -1
		return
	}
	session.SendUpdateFileEvent(sid, filepath.Join(curDirectory, util.GoModFile))
	session.SendUpdateFileEvent(sid, filepath.Join(curDirectory, util.GoSumFile))

	goos := strings.Split(platform, "_")[0]
	goarch := strings.Split(platform, "_")[1]
	suffix := ""
	if "windows" == goos {
		suffix = WindowsSuffix
	}
	executableFileName := filepath.Join(curDirectory, filepath.Base(curDirectory)+suffix)
	os.Remove(executableFileName)
	name := filepath.Base(curDirectory) + "-" + goos + "-" + goarch
	log.Errorf("evm build 111111. executableFileName:%s, file name:%s", executableFileName, name)
	user := conf.GetUser(uid)

	// 检查一下contract-sdk-go的版本看看是否需要条件编译指令
	needAddCompileTags := false
	hasImported, importedErr := util.CheckSrcImportChainmakerPackages(curDirectory)
	if importedErr != nil {
		log.Errorf("cross handler check go  file fail, err : %s", importedErr.Error())
		result.Code = -1
		result.Msg = importedErr.Error()
		return
	}
	if hasImported {
		needAddCompileTags = true
	}
	if !needAddCompileTags {
		needCompileNotAddTags, checkErr := util.CheckContractSdkNotAddTag(
			filepath.Join(curDirectory, util.GoModFile))
		if checkErr != nil {
			log.Errorf("cross handler check go mod file fail, err : %s", checkErr.Error())
			result.Code = -1
			result.Msg = checkErr.Error()
			return
		}
		needAddCompileTags = !needCompileNotAddTags
	}

	//编译
	var goBuildArgs []string
	goBuildArgs = append(goBuildArgs, "build", "-o", executableFileName, "-ldflags", "-s -w")
	if needAddCompileTags {
		goBuildArgs = append(goBuildArgs, "--tags", "crypto")
	}

	log.Errorf("go build 230执行参数为:%s curDirectory:%s", goBuildArgs, curDirectory)
	cmd := exec.Command(runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/go", goBuildArgs...)
	cmd.Dir = curDirectory
	//非测试环境执行环境变量设置
	if global.TestnetEnv != true {
		setCmdEnvWithOsAndArchAndGoRoot(cmd, uid, goos, goarch, os.Getenv("GOPATH"), runtime.GOROOT()+RealSdkGoRootSuffix)
	}

	stdout, stderr, err := util.OpenStdOutAndStdErr(cmd)
	if err != nil {
		log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}

	err = writeStartBuildMessageToWebSocket(sid, uid, user.Locale)
	if err != nil {
		log.Errorf("CrossCompilationHandler write start build message to websocket failed.uid:%s, err :%s", uid, err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}

	if err := cmd.Start(); nil != err {
		log.Errorf("CrossCompilationHandler start cmd faild. err:%s", err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}
	log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
	WaitCmdRunSuccess(rand.Int(), cmd, stdout, stderr, user.Locale, executableFileName, name, curDirectory, sid)

	file7z, err := generateBuildAndDeployFile(curDirectory, workspace, executableFileName, uid)
	if err != nil {
		log.Errorf("CrossCompilationHandler generate build file fail. err:%s", err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}

	result.Data = buildResponse{File: file7z}
}

func CrossDeployHandler(w http.ResponseWriter, r *http.Request) {
	uid, err := session.GetUidFromSession(r)
	if err != nil {
		log.Errorf("CrossCompilationHandler Forbidden. url:%s,uid:%s, err:%v", r.URL, uid, err)
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	result := gulu.Ret.NewResult()
	defer gulu.Ret.RetResult(w, r, result)

	var args map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		log.Errorf("CrossCompilationHandler decode parameter failed. url:%s, err:%v", r.URL, err)
		result.Code = -1
		return
	}
	sid := args["sid"].(string)
	platform := args["platform"].(string)
	contracttype := args["contract_type"].(string)
	contractName := args["contract_name"].(string)
	deploycontractName := args["deploy_contract_name"].(string)
	version := args["version"].(string)
	chaiId := args["chaiId"].(string)
	params := args["params"].(string)
	params = strings.Replace(params, `"`, `\"`, -1)
	////正式发布版本要改----
	////contracttype := "EVM"
	////contractName := "Hello"
	//contracttype := "Go"
	//contractName := "contract_demo01"
	//deploycontractName := "aaa351"
	//version := "3.2"
	//chaiId := "chain1"
	//params := ""

	log.Errorf("build -----333333----, sid:%s, platform:%s, contracttype:%s, contractName:%s, version:%s, chaiId:%s, params:%s", sid, platform, contracttype, contractName, version, chaiId, params)

	if sid == "" || platform == "" || contracttype == "" {
		http.Error(w, "parameter error", http.StatusBadRequest)
		return
	}

	workspace := conf.GetUserWorkspace(uid)

	contractDeployDir := conf.GetDeployContractDir(workspace, contractName)
	// 查build-info中的表数据
	compileInfo, compileQueryErr := conf.GetCompileInfo(uid, contractName)
	if compileQueryErr != nil {
		if gorm.IsRecordNotFoundError(compileQueryErr) {
			http.Error(w, "contract not found", http.StatusInternalServerError)
			return
		}
		log.Errorf("DeployHandler uid %s GetCompileInfo failed %s", uid, compileQueryErr.Error())
		http.Error(w, common.ErrorInternal, http.StatusInternalServerError)
	}
	// 检查一下deploy下文件夹是否存在
	newDeployDir := filepath.Join(contractDeployDir, compileInfo.BinMd5)
	if !util.FileExists(newDeployDir) {
		log.Errorf("DeployHandler uid %s, compileInfo [%+v], deploy not exists", uid, *compileInfo)
		http.Error(w, common.ErrorInternal, http.StatusInternalServerError)
		return
	}
	// 保存deploy-info表中的数据,
	deployInfo := conf.ConstructDeployInfoByCompileInfo(compileInfo)
	deployInfo.ContractName = deploycontractName
	saveErr := conf.SaveDeployInfo(deployInfo)
	if saveErr != nil {
		log.Errorf("DeployHandler uid %s , SaveDeployInfo [%+v] failed %s", uid, *deployInfo, saveErr.Error())
		http.Error(w, common.ErrorInternal, http.StatusInternalServerError)
		return
	}
	// 删除deploy下所有非hash的文件夹
	deleteDir, deleteDirErr := conf.RemoveAllSkip(contractDeployDir, []string{compileInfo.BinMd5})
	if deleteDirErr != nil {
		log.Errorf("DeployHandler uid %s , RemoveAllSkip failed %s", uid, deleteDirErr.Error())
	}
	log.Infof("DeployHandler uid %s , RemoveAllSkip %+v", uid, deleteDir)

	curDirectory := filepath.Dir(compileInfo.Path)
	log.Errorf("evm build -----111111. curDirectory:%s", curDirectory)

	if strings.EqualFold(contracttype, "EVM") {
		deployExecutableFileBIN := strings.TrimSuffix(compileInfo.Path, ".7z") + ".bin"
		deployExecutableFileABI := strings.TrimSuffix(compileInfo.Path, ".7z") + ".abi"
		nameNoExt := compileInfo.ContractName
		executableFile := nameNoExt + ".bin"
		//deploy
		//./cmc client contract user create \
		//--contract-name=balance001 \
		//--runtime-type=EVM \
		//--byte-code-path=./testdata/balance-evm-demo/ledger_balance.bin \
		//--abi-file-path=./testdata/balance-evm-demo/ledger_balance.abi \
		//--version=1.0 \
		//--sdk-conf-path=./testdata/sdk_config.yml \
		//--admin-key-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key,./testdata/crypto-config/wx-org2.chainmaker.org/user/admin1/admin1.sign.key,./testdata/crypto-config/wx-org3.chainmaker.org/user/admin1/admin1.sign.key \
		//--admin-crt-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt,./testdata/crypto-config/wx-org2.chainmaker.org/user/admin1/admin1.sign.crt,./testdata/crypto-config/wx-org3.chainmaker.org/user/admin1/admin1.sign.crt \
		//--sync-result=true
		goos := strings.Split(platform, "_")[0]
		goarch := strings.Split(platform, "_")[1]

		var goBuildArgs []string
		goBuildArgs = append(goBuildArgs, "client")
		goBuildArgs = append(goBuildArgs, "contract")
		goBuildArgs = append(goBuildArgs, "user")
		goBuildArgs = append(goBuildArgs, "create")
		goBuildArgs = append(goBuildArgs, "--contract-name="+deploycontractName)
		goBuildArgs = append(goBuildArgs, "--version="+version)
		goBuildArgs = append(goBuildArgs, "--sdk-conf-path="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/sdk_config.yml")
		goBuildArgs = append(goBuildArgs, "--byte-code-path="+deployExecutableFileBIN)
		goBuildArgs = append(goBuildArgs, "--abi-file-path="+deployExecutableFileABI)
		goBuildArgs = append(goBuildArgs, "--runtime-type=EVM")
		goBuildArgs = append(goBuildArgs, "--admin-crt-file-paths="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt")
		goBuildArgs = append(goBuildArgs, "--admin-key-file-paths="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key")
		goBuildArgs = append(goBuildArgs, "--sync-result=true")
		if params != "" {
			goBuildArgs = append(goBuildArgs, "--params=\""+params+"\"")
		}

		cmd := exec.Command(runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/cmc", goBuildArgs...)
		cmd.Dir = curDirectory
		//非测试环境执行环境变量设置
		if global.TestnetEnv != true {
			setCmdEnvWithOsAndArchAndGoRoot(cmd, uid, goos, goarch, os.Getenv("GOPATH"), runtime.GOROOT()+RealSdkGoRootSuffix)
		}

		stdout, stderr, err := util.OpenStdOutAndStdErr(cmd)
		if err != nil {
			log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err)
			result.Code = 0
			result.Msg = err.Error()
			return
		}

		user := conf.GetUser(uid)

		err = writeMessageToWebSocket(sid, uid, "deploy", "正在发布合约...")
		if err != nil {
			log.Errorf("deploy write start build message to websocket failed.uid:%s, err :%s", uid, err)
			result.Code = 0
			result.Msg = err.Error()
			return
		}

		if err := cmd.Start(); nil != err {
			log.Errorf("deploy start cmd faild. err:%s", err)
			result.Code = 0
			result.Msg = err.Error()
			return
		}
		log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
		WaitCmdRunSuccessEVM(rand.Int(), cmd, stdout, stderr, user.Locale, executableFile, nameNoExt, curDirectory, sid)

		if err != nil {
			log.Errorf("CrossCompilationHandler generate build file fail. err:%s", err)
			result.Code = -1
			result.Msg = err.Error()
			return
		}

		result.Code = 0
		result.Msg = "合约发布结束..."
		return
	}

	log.Errorf("evm build -----111222 deploy. curDirectory:%s", curDirectory)

	goos := strings.Split(platform, "_")[0]
	goarch := strings.Split(platform, "_")[1]
	executableFile := compileInfo.ContractName
	name := compileInfo.ContractName

	//deploy
	//cmc
	//client contract user create --contract-name=sharedata622
	//--version=2.0
	//--sync-result=true
	//--sdk-conf-path=./testdata/sdk_config.yml
	//--byte-code-path=/root/chainmaker/contracts-go/fact/sharedata622.7z
	//--runtime-type=DOCKER_GO
	//--admin-crt-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt
	//--admin-key-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key
	//--params=""
	//json format, such as: "{\"key\":\"value\",\"key1\":\"value1\"}"
	var goBuildArgs []string
	goBuildArgs = append(goBuildArgs, "client")
	goBuildArgs = append(goBuildArgs, "contract")
	goBuildArgs = append(goBuildArgs, "user")
	goBuildArgs = append(goBuildArgs, "create")
	goBuildArgs = append(goBuildArgs, "--contract-name="+deploycontractName)
	goBuildArgs = append(goBuildArgs, "--version="+version)
	goBuildArgs = append(goBuildArgs, "--sync-result=true")
	goBuildArgs = append(goBuildArgs, "--sdk-conf-path="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/sdk_config.yml")
	goBuildArgs = append(goBuildArgs, "--byte-code-path="+compileInfo.Path)
	goBuildArgs = append(goBuildArgs, "--runtime-type=DOCKER_GO")
	goBuildArgs = append(goBuildArgs, "--admin-crt-file-paths="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt")
	goBuildArgs = append(goBuildArgs, "--admin-key-file-paths="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key")
	if params != "" {
		goBuildArgs = append(goBuildArgs, "--params=\""+params+"\"")
	}

	cmd := exec.Command(runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/cmc", goBuildArgs...)
	cmd.Dir = curDirectory
	//非测试环境执行环境变量设置
	if global.TestnetEnv != true {
		setCmdEnvWithOsAndArchAndGoRoot(cmd, uid, goos, goarch, os.Getenv("GOPATH"), runtime.GOROOT()+RealSdkGoRootSuffix)
	}

	stdout, stderr, err := util.OpenStdOutAndStdErr(cmd)
	if err != nil {
		log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}

	user := conf.GetUser(uid)

	err = writeMessageToWebSocket(sid, uid, "deploy", "正在发布合约...")
	if err != nil {
		log.Errorf("deploy write start build message to websocket failed.uid:%s, err :%s", uid, err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}

	if err := cmd.Start(); nil != err {
		log.Errorf("deploy start cmd faild. err:%s", err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}
	log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
	WaitCmdRunSuccessEVM(rand.Int(), cmd, stdout, stderr, user.Locale, executableFile, name, curDirectory, sid)

	result.Code = 0
	result.Msg = "合约发布结束..."
	return

}

func InvokeAllContractHandler(w http.ResponseWriter, r *http.Request) {

	uid, err := session.GetUidFromSession(r)
	if err != nil {
		log.Errorf("CrossCompilationHandler Forbidden. url:%s,uid:%s, err:%v", r.URL, uid, err)
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	result := gulu.Ret.NewResult()
	defer gulu.Ret.RetResult(w, r, result)

	var args map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
		log.Errorf("CrossCompilationHandler decode parameter failed. url:%s, err:%v", r.URL, err)
		result.Code = -1
		return
	}
	sid := args["sid"].(string)
	platform := args["platform"].(string)
	contracttype := args["contract_type"].(string)
	contractName := args["contract_name"].(string)
	chaiId := args["chaiId"].(string)
	method := args["method"].(string)
	params := args["params"].(string)
	////正式发布版本要改----
	////contracttype := "EVM"
	////contractName := "Hello"
	//contracttype := "Go"
	//contractName := "contract_demo01"
	//deploycontractName := "aaa351"
	//version := "3.2"
	//chaiId := "chain1"
	//params := ""

	log.Errorf("build -----333333----, sid:%s, platform:%s, contracttype:%s, contractName:%s,  chaiId:%s, params:%s", sid, platform, contracttype, contractName, chaiId, params)

	if sid == "" || platform == "" || contracttype == "" {
		http.Error(w, "parameter error", http.StatusBadRequest)
		return
	}

	deployInfo, deployQueryErr := conf.GetDeployInfo(uid, contractName)
	if deployQueryErr != nil {
		log.Errorf("DeployHandler uid %s GetDeployInfo failed %s", uid, deployQueryErr.Error())
		http.Error(w, common.ErrorInternal, http.StatusInternalServerError)
	}

	// 查build-info中的表数据
	compileInfo, compileQueryErr := conf.GetvCompileByDeployInfo(deployInfo.SrcMd5, deployInfo.BinMd5)
	if compileQueryErr != nil {
		if gorm.IsRecordNotFoundError(compileQueryErr) {
			http.Error(w, "contract not found", http.StatusInternalServerError)
			return
		}
		log.Errorf("DeployHandler uid %s GetCompileInfo failed %s", uid, compileQueryErr.Error())
		http.Error(w, common.ErrorInternal, http.StatusInternalServerError)
	}

	curDirectory := filepath.Dir(compileInfo.Path)
	log.Errorf("evm build -----111111. curDirectory:%s", curDirectory)

	if strings.EqualFold(contracttype, "EVM") {
		deployExecutableFileABI := strings.TrimSuffix(compileInfo.Path, ".7z") + ".abi"
		nameNoExt := compileInfo.ContractName
		executableFile := nameNoExt + ".bin"

		goos := strings.Split(platform, "_")[0]
		goarch := strings.Split(platform, "_")[1]

		//$ ./cmc client contract user invoke \
		//--contract-name=balance001 \
		//--method=updateBalance \
		//--sdk-conf-path=./testdata/sdk_config.yml \
		//--params="[{\"uint256\": \"10000\"},{\"address\": \"0xa166c92f4c8118905ad984919dc683a7bdb295c1\"}]" \
		//--sync-result=true \
		//--abi-file-path=./testdata/balance-evm-demo/ledger_balance.abi

		var goBuildArgs []string
		goBuildArgs = append(goBuildArgs, "client")
		goBuildArgs = append(goBuildArgs, "contract")
		goBuildArgs = append(goBuildArgs, "user")
		goBuildArgs = append(goBuildArgs, "invoke")
		goBuildArgs = append(goBuildArgs, "--contract-name="+contractName)
		goBuildArgs = append(goBuildArgs, "--method="+method)
		goBuildArgs = append(goBuildArgs, "--sdk-conf-path="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/sdk_config.yml")
		goBuildArgs = append(goBuildArgs, "--sync-result=true")
		goBuildArgs = append(goBuildArgs, "--abi-file-path="+deployExecutableFileABI)
		if params != "" {
			goBuildArgs = append(goBuildArgs, "--params="+convertString2SliceString(params))
		}

		cmd := exec.Command(runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/cmc", goBuildArgs...)
		cmd.Dir = curDirectory
		//非测试环境执行环境变量设置
		if global.TestnetEnv != true {
			setCmdEnvWithOsAndArchAndGoRoot(cmd, uid, goos, goarch, os.Getenv("GOPATH"), runtime.GOROOT()+RealSdkGoRootSuffix)
		}

		stdout, stderr, err := util.OpenStdOutAndStdErr(cmd)
		if err != nil {
			log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err)
			result.Code = 0
			result.Msg = err.Error()
			return
		}

		user := conf.GetUser(uid)

		err = writeMessageToWebSocket(sid, uid, "deploy", "正在调用合约...")
		if err != nil {
			log.Errorf("deploy write start build message to websocket failed.uid:%s, err :%s", uid, err)
			result.Code = 0
			result.Msg = err.Error()
			return
		}

		if err := cmd.Start(); nil != err {
			log.Errorf("deploy start cmd faild. err:%s", err)
			result.Code = 0
			result.Msg = err.Error()
			return
		}
		log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
		WaitCmdRunSuccessEVM(rand.Int(), cmd, stdout, stderr, user.Locale, executableFile, nameNoExt, curDirectory, sid)

		if err != nil {
			log.Errorf("CrossCompilationHandler generate build file fail. err:%s", err)
			result.Code = -1
			result.Msg = err.Error()
			return
		}

		result.Code = 0
		result.Msg = "合约谳用成功..."
		return
	}

	goos := strings.Split(platform, "_")[0]
	goarch := strings.Split(platform, "_")[1]
	executableFile := compileInfo.ContractName
	name := compileInfo.ContractName

	//调用wasm合约
	//
	//$ ./cmc client contract user invoke \
	//--contract-name=fact \
	//--method=save \
	//--sdk-conf-path=./testdata/sdk_config.yml \
	//--params="{\"file_name\":\"name007\",\"file_hash\":\"ab3456df5799b87c77e7f88\",\"time\":\"6543234\"}" \
	//--sync-result=true
	//调用evm合约
	//
	//json format, such as: "{\"key\":\"value\",\"key1\":\"value1\"}"
	var goBuildArgs []string
	goBuildArgs = append(goBuildArgs, "client")
	goBuildArgs = append(goBuildArgs, "contract")
	goBuildArgs = append(goBuildArgs, "user")
	goBuildArgs = append(goBuildArgs, "invoke")
	goBuildArgs = append(goBuildArgs, "--contract-name="+contractName)
	goBuildArgs = append(goBuildArgs, "--method="+strings.ToLower(method))
	goBuildArgs = append(goBuildArgs, "--sdk-conf-path="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/sdk_config.yml")
	if params != "" {
		goBuildArgs = append(goBuildArgs, "--params="+params)
	}
	goBuildArgs = append(goBuildArgs, "--sync-result=true")

	cmd := exec.Command(runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/cmc", goBuildArgs...)
	cmd.Dir = curDirectory
	//非测试环境执行环境变量设置
	if global.TestnetEnv != true {
		setCmdEnvWithOsAndArchAndGoRoot(cmd, uid, goos, goarch, os.Getenv("GOPATH"), runtime.GOROOT()+RealSdkGoRootSuffix)
	}

	stdout, stderr, err := util.OpenStdOutAndStdErr(cmd)
	if err != nil {
		log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}

	user := conf.GetUser(uid)

	err = writeMessageToWebSocket(sid, uid, "deploy", "正在调用合约...")
	if err != nil {
		log.Errorf("deploy write start build message to websocket failed.uid:%s, err :%s", uid, err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}

	if err := cmd.Start(); nil != err {
		log.Errorf("deploy start cmd faild. err:%s", err)
		result.Code = -1
		result.Msg = err.Error()
		return
	}
	log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
	WaitCmdRunSuccessEVM(rand.Int(), cmd, stdout, stderr, user.Locale, executableFile, name, curDirectory, sid)

	result.Code = 0
	result.Msg = "合约调用成功..."
	return
}

func writeStartBuildMessageToWebSocket(sid, uid, locale string) error {
	channelRet := map[string]interface{}{}
	if wsChannel, err := session.GetOutputWS(sid); err == nil {
		channelRet["output"] = "<span class='start-build'>" + i18n.Get(locale, "start-build").(string) + "</span>\n"
		channelRet["cmd"] = "start-build"
		err := wsChannel.WriteJSON(&channelRet)
		if nil != err {
			return errors.New("write message to socket failed")
		}
		wsChannel.Refresh()
	} else {
		log.Errorf("CrossCompilationHandler websocket not found. uid:%s, msg:%v", uid, channelRet)
		return errors.New("web socket not found")
	}
	return nil
}

func writeMessageToWebSocket(sid, uid, cmd, Message string) error {
	channelRet := map[string]interface{}{}
	if wsChannel, err := session.GetOutputWS(sid); err == nil {
		channelRet["output"] = "<span class='start-build'>" + Message + "</span>\n"
		channelRet["cmd"] = cmd
		err := wsChannel.WriteJSON(&channelRet)
		if nil != err {
			return errors.New("write message to socket failed")
		}
		wsChannel.Refresh()
	} else {
		log.Errorf("CrossCompilationHandler websocket not found. uid:%s, msg:%v", uid, channelRet)
		return errors.New("web socket not found")
	}
	return nil
}

func WaitCmdRunSuccess(runningID int, cmd *exec.Cmd, stdout io.ReadCloser, stderr io.ReadCloser,
	locale, executable, name, curDirectory, sid string) {
	log.Debugf("WaitCmdRunSuccess start. directory%s, sid:%s, runing id:%d", curDirectory, sid, runningID)
	defer util.PanicLog()
	bytes, err := ioutil.ReadAll(bufio.NewReader(io.MultiReader(stdout, stderr)))
	if err != nil {
		log.Infof("WaitCmdRunSuccess read stdout std err failed. err:%s", err)
		return
	}
	stdOutput := string(bytes)
	channelRet := map[string]interface{}{}
	channelRet["cmd"] = "cross-build"
	channelRet["executable"] = executable
	channelRet["name"] = name

	if 0 == len(stdOutput) { // build success
		log.Warnf("WaitCmdRunSuccess std output: %s", stdOutput)
		channelRet["output"] = "<span class='build-succ'>" + i18n.Get(locale, "build-succ").(string) + "</span>\n"
	} else {
		lines := strings.Split(stdOutput, "\n")
		log.Debugf("outlines: %v \n", lines)
		var stdOutWithPath string
		for _, line := range lines {
			stdOutWithPath += parsePath(curDirectory, line) + "\n"
		}

		channelRet["output"] = "<span class='build-error'>" + i18n.Get(locale, "build-error").(string) + "</span>\n" +
			"<span class='stderr'>" + stdOutWithPath + "</span>"

		channelRet["lints"] = parseLints(lines, curDirectory)
	}

	if wsChannel, err := session.GetOutputWS(sid); err == nil {
		err := wsChannel.WriteJSON(&channelRet)
		if nil != err {
			log.Errorf("WaitCmdRunSuccess write message to websocket error. err:%s", err)
		}
		wsChannel.Refresh()
	}

	err = cmd.Wait()
	if err != nil {
		log.Errorf("WaitCmdRunSuccess cmd wait error. err:%s", err)
	}
}

func WaitCmdRunSuccessEVM(runningID int, cmd *exec.Cmd, stdout io.ReadCloser, stderr io.ReadCloser,
	locale, executable, name, curDirectory, sid string) {
	log.Debugf("WaitCmdRunSuccess start. directory%s, sid:%s, runing id:%d", curDirectory, sid, runningID)
	defer util.PanicLog()
	bytes, err := ioutil.ReadAll(bufio.NewReader(io.MultiReader(stdout, stderr)))
	if err != nil {
		log.Infof("WaitCmdRunSuccess read stdout std err failed. err:%s", err)
		return
	}
	stdOutput := string(bytes)
	channelRet := map[string]interface{}{}
	channelRet["cmd"] = "cross-build"
	channelRet["executable"] = executable
	channelRet["name"] = name
	channelRet["output"] = "<span class='build-succ'>" + stdOutput + "</span>\n"

	if wsChannel, err := session.GetOutputWS(sid); err == nil {
		err := wsChannel.WriteJSON(&channelRet)
		if nil != err {
			log.Errorf("WaitCmdRunSuccess write message to websocket error. err:%s", err)
		}
		wsChannel.Refresh()
	}

	err = cmd.Wait()
	if err != nil {
		log.Errorf("WaitCmdRunSuccess cmd wait error. err:%s", err)
	}
}

func parseLints(lines []string, curDirectory string) []*Lint {
	lints := make([]*Lint, 0)

	if lines[0][0] == '#' {
		lines = lines[1:] // skip the first line
	}

	for _, line := range lines {
		if len(line) < 1 {
			continue
		}

		if line[0] == '\t' {
			last := len(lints)
			msg := lints[last-1].Msg
			msg += line
			lints[last-1].Msg = msg
			continue
		}

		fileName := line[:strings.Index(line, ":")]
		left := line[strings.Index(line, ":")+1:]
		index := strings.Index(left, ":")
		lineNo := 0
		var err error
		msg := left
		if index >= 0 {
			lineNo, err = strconv.Atoi(left[:index])
			if nil != err {
				continue
			}
			msg = left[index+2:]
		}

		lint := &Lint{
			File:     filepath.Join(curDirectory, fileName),
			LineNo:   lineNo - 1,
			Severity: lintSeverityError,
			Msg:      msg,
		}

		lints = append(lints, lint)
	}
	return lints
}

// generateBuildFile generate build file after build
func generateBuildAndDeployFile(curDirectory, workspace, executableFile, uid string) (string, error) {
	doRet, doRetErr, _ := crossBuildSg.Do(curDirectory, func() (interface{}, error) {
		if !util.FileExists(executableFile) {
			return "", fmt.Errorf("file: %s not exist", executableFile)
		}
		contractDirectoryName := filepath.Base(curDirectory)
		// 删除build-info表数据
		deleteErr := conf.DeleteCompileInfo(uid, contractDirectoryName)
		if deleteErr != nil {
			log.Errorf("generateBuildAndDeployFile uid %s, DeleteCompileInfo %s ,failed %s",
				uid, contractDirectoryName, deleteErr.Error())
			return "", deleteErr
		}
		// 删除build/contractDirectoryName下所有
		tempDir := conf.GetBuildContractDir(workspace, contractDirectoryName)
		os.RemoveAll(tempDir)
		//create build directory
		buildDirectory, err := conf.CreateBuildContractDir(workspace, contractDirectoryName)
		if err != nil {
			log.Errorf("generateBuildFile create build directory fail.uid:%s, err :%s", uid, err)
			return "", err
		}

		//copy executable file to build directory
		deployExecutableFile := filepath.Join(buildDirectory, filepath.Base(executableFile))
		err = util.CopyFile(executableFile, deployExecutableFile)
		if err != nil {
			log.Errorf("generateBuildFile copy file fail.uid:%s, err :%s", uid, err)
			return "", err
		}
		//compress executable file to build directory
		fileName7z, err := util.Compress7z(buildDirectory, filepath.Base(executableFile))
		if err != nil {
			log.Errorf("generateBuildFile compress file fail. uid:%s, build dir:%s, execute file:%s,  err :%s",
				uid, buildDirectory, executableFile, err)
			return "", err
		}
		//remove executable file
		//err = os.Remove(executableFile)
		//if err != nil {
		//	log.Errorf("generateBuildFile remove executable file fail. uid:%s, executable file:%s, err :%s",
		//		uid, executableFile, err)
		//	return "", err
		//}

		//create deploy directory
		deployDirectory, err := conf.CreateDeployContractDir(workspace, contractDirectoryName)
		if err != nil {
			log.Errorf("generateBuildFile create deploy directory fail. "+
				"uid:%s, workspace:%s, contract dir name:%s, err :%s", uid, workspace, contractDirectoryName, err)
			return "", err
		}

		file7z := filepath.Join(buildDirectory, fileName7z)
		fileData, err := ioutil.ReadFile(file7z)
		sm3Sum := sm3.Sm3Sum(fileData)
		md5SumHex := hex.EncodeToString(sm3Sum[:])

		hashDir, err := conf.CreateDeployHashDir(deployDirectory, md5SumHex)
		if err != nil {
			log.Errorf("generateBuildFile create has directory fail. "+
				"uid:%s, deploy dir:%s, md5:%s, hash dir:%s, err :%s",
				uid, deployDirectory, md5SumHex, hashDir, err)
			return "", err
		}
		// __source_code.7z
		source7zName := conf.GetSource7zName()
		compressSource := curDirectory
		compressTarget := filepath.Join(hashDir, source7zName)
		//compress source code to 7z
		err = util.Compress7zSourceToTarget(compressSource, compressTarget)
		if err != nil {
			log.Errorf("generateBuildFile compress source code fial. "+
				"uid:%s,compress source:%s,compress target:%s, err :%s", uid, compressSource, compressTarget, err)
			return "", err
		}

		//source code hash
		sourceCodeData, err := ioutil.ReadFile(compressTarget)
		sourceCodeSm3Sum := sm3.Sm3Sum(sourceCodeData)
		sourceCodeMd5SumHex := hex.EncodeToString(sourceCodeSm3Sum[:])

		//copy binary file
		hashExecutableFile := filepath.Join(hashDir, filepath.Base(executableFile))
		err = util.CopyFile(deployExecutableFile, hashExecutableFile)
		if err != nil {
			log.Errorf("generateBuildFile copy binary file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, deployExecutableFile, hashExecutableFile, err)
			return "", err
		}
		//copy compress file
		source7z := filepath.Join(buildDirectory, fileName7z)
		target7z := filepath.Join(hashDir, fileName7z)
		err = util.CopyFile(source7z, target7z)
		if err != nil {
			log.Errorf("generateBuildFile copy compress file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, source7z, target7z, err)
			return "", err
		}
		// 保存 build信息到build-info表格
		compileInfo := generateBuildInfoNew(uid, curDirectory, file7z, contractDirectoryName, md5SumHex, sourceCodeMd5SumHex)
		saveErr := conf.SaveCompileInfo(compileInfo)
		if saveErr != nil {
			log.Errorf("")
			return "", saveErr
		}
		return file7z, nil
	})
	return doRet.(string), doRetErr
}

func generateBuildAndDeploy(curDirectory, workspace, executableFile, uid, sid, platform, name, chaiId, contractName, version, params string) (string, error) {
	doRet, doRetErr, _ := crossBuildSg.Do(curDirectory, func() (interface{}, error) {
		if !util.FileExists(executableFile) {
			return "", fmt.Errorf("file: %s not exist", executableFile)
		}
		contractDirectoryName := filepath.Base(curDirectory)
		// 删除build-info表数据
		deleteErr := conf.DeleteCompileInfo(uid, contractDirectoryName)
		if deleteErr != nil {
			log.Errorf("generateBuildAndDeployFile uid %s, DeleteCompileInfo %s ,failed %s",
				uid, contractDirectoryName, deleteErr.Error())
			return "", deleteErr
		}
		// 删除build/contractDirectoryName下所有
		tempDir := conf.GetBuildContractDir(workspace, contractDirectoryName)
		os.RemoveAll(tempDir)
		//create build directory
		buildDirectory, err := conf.CreateBuildContractDir(workspace, contractDirectoryName)
		if err != nil {
			log.Errorf("generateBuildFile create build directory fail.uid:%s, err :%s", uid, err)
			return "", err
		}

		//copy executable file to build directory
		deployExecutableFile := filepath.Join(buildDirectory, filepath.Base(executableFile))
		err = util.CopyFile(executableFile, deployExecutableFile)
		if err != nil {
			log.Errorf("generateBuildFile copy file fail.uid:%s, err :%s", uid, err)
			return "", err
		}
		//compress executable file to build directory
		fileName7z, err := util.Compress7z(buildDirectory, filepath.Base(executableFile))
		if err != nil {
			log.Errorf("generateBuildFile compress file fail. uid:%s, build dir:%s, execute file:%s,  err :%s",
				uid, buildDirectory, executableFile, err)
			return "", err
		}
		//remove executable file
		err = os.Remove(executableFile)
		if err != nil {
			log.Errorf("generateBuildFile remove executable file fail. uid:%s, executable file:%s, err :%s",
				uid, executableFile, err)
			return "", err
		}

		log.Errorf("evm build -----555555. contractDirectoryName:%s", contractDirectoryName)

		//create deploy directory
		deployDirectory, err := conf.CreateDeployContractDir(workspace, contractDirectoryName)
		if err != nil {
			log.Errorf("generateBuildFile create deploy directory fail. "+
				"uid:%s, workspace:%s, contract dir name:%s, err :%s", uid, workspace, contractDirectoryName, err)
			return "", err
		}

		file7z := filepath.Join(buildDirectory, fileName7z)
		fileData, err := ioutil.ReadFile(file7z)
		sm3Sum := sm3.Sm3Sum(fileData)
		md5SumHex := hex.EncodeToString(sm3Sum[:])

		hashDir, err := conf.CreateDeployHashDir(deployDirectory, md5SumHex)
		if err != nil {
			log.Errorf("generateBuildFile create has directory fail. "+
				"uid:%s, deploy dir:%s, md5:%s, hash dir:%s, err :%s",
				uid, deployDirectory, md5SumHex, hashDir, err)
			return "", err
		}
		// __source_code.7z
		source7zName := conf.GetSource7zName()
		compressSource := curDirectory
		compressTarget := filepath.Join(hashDir, source7zName)
		//compress source code to 7z
		err = util.Compress7zSourceToTarget(compressSource, compressTarget)
		if err != nil {
			log.Errorf("generateBuildFile compress source code fial. "+
				"uid:%s,compress source:%s,compress target:%s, err :%s", uid, compressSource, compressTarget, err)
			return "", err
		}

		//source code hash
		sourceCodeData, err := ioutil.ReadFile(compressTarget)
		sourceCodeSm3Sum := sm3.Sm3Sum(sourceCodeData)
		sourceCodeMd5SumHex := hex.EncodeToString(sourceCodeSm3Sum[:])

		//copy binary file
		hashExecutableFile := filepath.Join(hashDir, filepath.Base(executableFile))
		err = util.CopyFile(deployExecutableFile, hashExecutableFile)
		if err != nil {
			log.Errorf("generateBuildFile copy binary file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, deployExecutableFile, hashExecutableFile, err)
			return "", err
		}
		//copy compress file
		source7z := filepath.Join(buildDirectory, fileName7z)
		target7z := filepath.Join(hashDir, fileName7z)
		err = util.CopyFile(source7z, target7z)
		if err != nil {
			log.Errorf("generateBuildFile copy compress file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, source7z, target7z, err)
			return "", err
		}
		// 保存 build信息到build-info表格
		compileInfo := generateBuildInfoNew(uid, curDirectory, file7z, contractDirectoryName, md5SumHex, sourceCodeMd5SumHex)
		saveErr := conf.SaveCompileInfo(compileInfo)
		if saveErr != nil {
			log.Errorf("")
			return "", saveErr
		}

		//deploy
		//cmc
		//client contract user create --contract-name=sharedata622
		//--version=2.0
		//--sync-result=true
		//--sdk-conf-path=./testdata/sdk_config.yml
		//--byte-code-path=/root/chainmaker/contracts-go/fact/sharedata622.7z
		//--runtime-type=DOCKER_GO
		//--admin-crt-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt
		//--admin-key-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key
		//--params=""
		//json format, such as: "{\"key\":\"value\",\"key1\":\"value1\"}"
		goos := strings.Split(platform, "_")[0]
		goarch := strings.Split(platform, "_")[1]

		var goBuildArgs []string
		goBuildArgs = append(goBuildArgs, "client")
		goBuildArgs = append(goBuildArgs, "contract")
		goBuildArgs = append(goBuildArgs, "user")
		goBuildArgs = append(goBuildArgs, "create")
		goBuildArgs = append(goBuildArgs, "--contract-name="+contractName)
		goBuildArgs = append(goBuildArgs, "--version="+version)
		goBuildArgs = append(goBuildArgs, "--sync-result=true")
		goBuildArgs = append(goBuildArgs, "--sdk-conf-path="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/sdk_config.yml")
		goBuildArgs = append(goBuildArgs, "--byte-code-path="+filepath.Join(buildDirectory, filepath.Base(curDirectory)+".7z"))
		goBuildArgs = append(goBuildArgs, "--runtime-type=DOCKER_GO")
		goBuildArgs = append(goBuildArgs, "--admin-crt-file-paths="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt")
		goBuildArgs = append(goBuildArgs, "--admin-key-file-paths="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key")
		if params != "" {
			goBuildArgs = append(goBuildArgs, "--params=\""+params+"\"")
		}

		cmd := exec.Command(runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/cmc", goBuildArgs...)
		cmd.Dir = curDirectory
		//非测试环境执行环境变量设置
		if global.TestnetEnv != true {
			setCmdEnvWithOsAndArchAndGoRoot(cmd, uid, goos, goarch, os.Getenv("GOPATH"), runtime.GOROOT()+RealSdkGoRootSuffix)
		}

		stdout, stderr, err := util.OpenStdOutAndStdErr(cmd)
		if err != nil {
			log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err)
			return nil, nil
		}

		user := conf.GetUser(uid)

		err = writeMessageToWebSocket(sid, uid, "deploy", "正在发布合约...")
		if err != nil {
			log.Errorf("deploy write start build message to websocket failed.uid:%s, err :%s", uid, err)
			return nil, nil
		}

		if err := cmd.Start(); nil != err {
			log.Errorf("deploy start cmd faild. err:%s", err)
			return nil, nil
		}
		log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
		WaitCmdRunSuccessEVM(rand.Int(), cmd, stdout, stderr, user.Locale, executableFile, name, curDirectory, sid)

		return file7z, nil
	})
	return doRet.(string), doRetErr
}

func generateBuildAndDeployFileEvm(curDirectory, workspace, nameNoExt, uid string) (string, error) {
	doRet, doRetErr, _ := crossBuildSg.Do(curDirectory, func() (interface{}, error) {
		if !util.FileExists(filepath.Join(curDirectory, " out", nameNoExt+".abi")) {
			return "", fmt.Errorf("file: %s not exist", nameNoExt+".abi")
		}
		// 删除build-info表数据
		deleteErr := conf.DeleteCompileInfo(uid, nameNoExt)
		if deleteErr != nil {
			log.Errorf("generateBuildAndDeployFile uid %s, DeleteCompileInfo %s ,failed %s",
				uid, nameNoExt, deleteErr.Error())
			return "", deleteErr
		}
		// 删除build/contractDirectoryName下所有
		tempDir := conf.GetBuildContractDir(workspace, nameNoExt)
		os.RemoveAll(tempDir)
		//create build directory
		buildDirectory, err := conf.CreateBuildContractDir(workspace, nameNoExt)
		if err != nil {
			log.Errorf("generateBuildFile create build directory fail.uid:%s, err :%s", uid, err)
			return "", err
		}

		//copy executable file to build directory
		deployExecutableFileABI := filepath.Join(buildDirectory, filepath.Base(nameNoExt)+".abi")
		err = util.CopyFile(filepath.Join(curDirectory, " out", nameNoExt+".abi"), deployExecutableFileABI)
		if err != nil {
			log.Errorf("generateBuildFile copy abi file fail.uid:%s, err :%s", uid, err)
			return "", err
		}
		deployExecutableFileBIN := filepath.Join(buildDirectory, filepath.Base(nameNoExt)+".bin")
		err = util.CopyFile(filepath.Join(curDirectory, " out", nameNoExt+".bin"), deployExecutableFileBIN)
		if err != nil {
			log.Errorf("generateBuildFile copy bin file fail.uid:%s, err :%s", uid, err)
			return "", err
		}
		deployExecutableFileJAVA := filepath.Join(buildDirectory, filepath.Base(nameNoExt)+".java")
		err = util.CopyFile(filepath.Join(curDirectory, "framework", nameNoExt+".java"), deployExecutableFileJAVA)
		if err != nil {
			log.Errorf("generateBuildFile copy java file fail.uid:%s, err :%s", uid, err)
			return "", err
		}
		//compress executable file to build directory
		_, err1 := util.Compress7zFiles(buildDirectory, filepath.Base(nameNoExt), deployExecutableFileABI)
		if err1 != nil {
			log.Errorf("generateBuildFile compress file abi fail. uid:%s, build dir:%s, execute file:%s,  err :%s",
				uid, buildDirectory, deployExecutableFileABI, err)
			return "", err
		}
		_, err2 := util.Compress7zFiles(buildDirectory, filepath.Base(nameNoExt), deployExecutableFileBIN)
		if err2 != nil {
			log.Errorf("generateBuildFile compress bin file fail. uid:%s, build dir:%s, execute file:%s,  err :%s",
				uid, buildDirectory, deployExecutableFileBIN, err)
			return "", err
		}

		fileName7z, err := util.Compress7zFiles(buildDirectory, filepath.Base(nameNoExt), deployExecutableFileJAVA)
		if err != nil {
			log.Errorf("generateBuildFile compress java file fail. uid:%s, build dir:%s, execute file:%s,  err :%s",
				uid, buildDirectory, deployExecutableFileJAVA, err)
			return "", err
		}
		//remove executable file
		//err = os.Remove(filepath.Join(curDirectory, " out", executableFile+".abi"))
		//if err != nil {
		//	log.Errorf("generateBuildFile remove executable file fail. uid:%s, executable file:%s, err :%s",
		//		uid, executableFile+".abi", err)
		//	return "", err
		//}
		//
		//err = os.Remove(filepath.Join(curDirectory, " out", executableFile+".bin"))
		//if err != nil {
		//	log.Errorf("generateBuildFile remove executable file fail. uid:%s, executable file:%s, err :%s",
		//		uid, executableFile+".bin", err)
		//	return "", err
		//}

		//create deploy directory
		deployDirectory, err := conf.CreateDeployContractDir(workspace, nameNoExt)
		if err != nil {
			log.Errorf("generateBuildFile create deploy directory fail. "+
				"uid:%s, workspace:%s, contract dir name:%s, err :%s", uid, workspace, nameNoExt, err)
			return "", err
		}

		file7z := filepath.Join(buildDirectory, fileName7z)
		fileData, err := ioutil.ReadFile(file7z)
		sm3Sum := sm3.Sm3Sum(fileData)
		md5SumHex := hex.EncodeToString(sm3Sum[:])

		hashDir, err := conf.CreateDeployHashDir(deployDirectory, md5SumHex)
		if err != nil {
			log.Errorf("generateBuildFile create has directory fail. "+
				"uid:%s, deploy dir:%s, md5:%s, hash dir:%s, err :%s",
				uid, deployDirectory, md5SumHex, hashDir, err)
			return "", err
		}
		// __source_code.7z
		source7zName := conf.GetSource7zName()
		compressSource := curDirectory
		compressTarget := filepath.Join(hashDir, source7zName)
		//compress source code to 7z
		err = util.Compress7zSourceToTarget(compressSource, compressTarget)
		if err != nil {
			log.Errorf("generateBuildFile compress source code fial. "+
				"uid:%s,compress source:%s,compress target:%s, err :%s", uid, compressSource, compressTarget, err)
			return "", err
		}

		//source code hash
		sourceCodeData, err := ioutil.ReadFile(compressTarget)
		sourceCodeSm3Sum := sm3.Sm3Sum(sourceCodeData)
		sourceCodeMd5SumHex := hex.EncodeToString(sourceCodeSm3Sum[:])

		//copy binary file
		hashExecutableFileBIN := filepath.Join(hashDir, filepath.Base(nameNoExt)+".bin")
		hashExecutableFileABI := filepath.Join(hashDir, filepath.Base(nameNoExt)+".abi")
		hashExecutableFileJAVA := filepath.Join(hashDir, filepath.Base(nameNoExt)+".java")
		err = util.CopyFile(deployExecutableFileBIN, hashExecutableFileBIN)
		if err != nil {
			log.Errorf("generateBuildFile copy binary file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, deployExecutableFileBIN, hashExecutableFileBIN, err)
			return "", err
		}
		err = util.CopyFile(deployExecutableFileABI, hashExecutableFileABI)
		if err != nil {
			log.Errorf("generateBuildFile copy binary file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, deployExecutableFileABI, hashExecutableFileABI, err)
			return "", err
		}
		err = util.CopyFile(deployExecutableFileJAVA, hashExecutableFileJAVA)
		if err != nil {
			log.Errorf("generateBuildFile copy binary file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, deployExecutableFileJAVA, hashExecutableFileJAVA, err)
			return "", err
		}
		//copy compress file
		source7z := filepath.Join(buildDirectory, fileName7z)
		target7z := filepath.Join(hashDir, fileName7z)
		err = util.CopyFile(source7z, target7z)
		if err != nil {
			log.Errorf("generateBuildFile copy compress file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, source7z, target7z, err)
			return "", err
		}

		// 保存 build信息到build-info表格
		compileInfo := generateBuildInfoNew(uid, curDirectory, file7z, nameNoExt, md5SumHex, sourceCodeMd5SumHex)
		saveErr := conf.SaveCompileInfo(compileInfo)
		if saveErr != nil {
			log.Errorf("")
			return "", saveErr
		}
		return file7z, nil
	})
	return doRet.(string), doRetErr
}

func generateBuildAndDeployEVM(curDirectory, workspace, executableFile, uid, sid, platform, nameNoExt, chaiId, contractName, version, params string) (string, error) {
	doRet, doRetErr, _ := crossBuildSg.Do(curDirectory, func() (interface{}, error) {
		if !util.FileExists(filepath.Join(curDirectory, " out", executableFile+".abi")) {
			return "", fmt.Errorf("file: %s not exist", executableFile+".abi")
		}
		// 删除build-info表数据
		deleteErr := conf.DeleteCompileInfo(uid, nameNoExt)
		if deleteErr != nil {
			log.Errorf("generateBuildAndDeployFile uid %s, DeleteCompileInfo %s ,failed %s",
				uid, nameNoExt, deleteErr.Error())
			return "", deleteErr
		}
		// 删除build/contractDirectoryName下所有
		tempDir := conf.GetBuildContractDir(workspace, nameNoExt)
		os.RemoveAll(tempDir)
		//create build directory
		buildDirectory, err := conf.CreateBuildContractDir(workspace, nameNoExt)
		if err != nil {
			log.Errorf("generateBuildFile create build directory fail.uid:%s, err :%s", uid, err)
			return "", err
		}

		//copy executable file to build directory
		deployExecutableFileABI := filepath.Join(buildDirectory, filepath.Base(executableFile)+".abi")
		err = util.CopyFile(filepath.Join(curDirectory, " out", executableFile+".abi"), deployExecutableFileABI)
		if err != nil {
			log.Errorf("generateBuildFile copy abi file fail.uid:%s, err :%s", uid, err)
			return "", err
		}
		deployExecutableFileBIN := filepath.Join(buildDirectory, filepath.Base(executableFile)+".bin")
		err = util.CopyFile(filepath.Join(curDirectory, " out", executableFile+".bin"), deployExecutableFileBIN)
		if err != nil {
			log.Errorf("generateBuildFile copy bin file fail.uid:%s, err :%s", uid, err)
			return "", err
		}
		deployExecutableFileJAVA := filepath.Join(buildDirectory, filepath.Base(executableFile)+".java")
		err = util.CopyFile(filepath.Join(curDirectory, "framework", executableFile+".java"), deployExecutableFileJAVA)
		if err != nil {
			log.Errorf("generateBuildFile copy java file fail.uid:%s, err :%s", uid, err)
			return "", err
		}
		//compress executable file to build directory
		_, err1 := util.Compress7zFiles(buildDirectory, filepath.Base(executableFile), deployExecutableFileABI)
		if err1 != nil {
			log.Errorf("generateBuildFile compress file abi fail. uid:%s, build dir:%s, execute file:%s,  err :%s",
				uid, buildDirectory, deployExecutableFileABI, err)
			return "", err
		}
		_, err2 := util.Compress7zFiles(buildDirectory, filepath.Base(executableFile), deployExecutableFileBIN)
		if err2 != nil {
			log.Errorf("generateBuildFile compress bin file fail. uid:%s, build dir:%s, execute file:%s,  err :%s",
				uid, buildDirectory, deployExecutableFileBIN, err)
			return "", err
		}

		fileName7z, err := util.Compress7zFiles(buildDirectory, filepath.Base(executableFile), deployExecutableFileJAVA)
		if err != nil {
			log.Errorf("generateBuildFile compress java file fail. uid:%s, build dir:%s, execute file:%s,  err :%s",
				uid, buildDirectory, deployExecutableFileJAVA, err)
			return "", err
		}
		//remove executable file
		//err = os.Remove(filepath.Join(curDirectory, " out", executableFile+".abi"))
		//if err != nil {
		//	log.Errorf("generateBuildFile remove executable file fail. uid:%s, executable file:%s, err :%s",
		//		uid, executableFile+".abi", err)
		//	return "", err
		//}
		//
		//err = os.Remove(filepath.Join(curDirectory, " out", executableFile+".bin"))
		//if err != nil {
		//	log.Errorf("generateBuildFile remove executable file fail. uid:%s, executable file:%s, err :%s",
		//		uid, executableFile+".bin", err)
		//	return "", err
		//}

		//create deploy directory
		deployDirectory, err := conf.CreateDeployContractDir(workspace, nameNoExt)
		if err != nil {
			log.Errorf("generateBuildFile create deploy directory fail. "+
				"uid:%s, workspace:%s, contract dir name:%s, err :%s", uid, workspace, nameNoExt, err)
			return "", err
		}

		file7z := filepath.Join(buildDirectory, fileName7z)
		fileData, err := ioutil.ReadFile(file7z)
		sm3Sum := sm3.Sm3Sum(fileData)
		md5SumHex := hex.EncodeToString(sm3Sum[:])

		hashDir, err := conf.CreateDeployHashDir(deployDirectory, md5SumHex)
		if err != nil {
			log.Errorf("generateBuildFile create has directory fail. "+
				"uid:%s, deploy dir:%s, md5:%s, hash dir:%s, err :%s",
				uid, deployDirectory, md5SumHex, hashDir, err)
			return "", err
		}
		// __source_code.7z
		source7zName := conf.GetSource7zName()
		compressSource := curDirectory
		compressTarget := filepath.Join(hashDir, source7zName)
		//compress source code to 7z
		err = util.Compress7zSourceToTarget(compressSource, compressTarget)
		if err != nil {
			log.Errorf("generateBuildFile compress source code fial. "+
				"uid:%s,compress source:%s,compress target:%s, err :%s", uid, compressSource, compressTarget, err)
			return "", err
		}

		//source code hash
		sourceCodeData, err := ioutil.ReadFile(compressTarget)
		sourceCodeSm3Sum := sm3.Sm3Sum(sourceCodeData)
		sourceCodeMd5SumHex := hex.EncodeToString(sourceCodeSm3Sum[:])

		//copy binary file
		hashExecutableFileBIN := filepath.Join(hashDir, filepath.Base(executableFile)+".bin")
		hashExecutableFileABI := filepath.Join(hashDir, filepath.Base(executableFile)+".abi")
		hashExecutableFileJAVA := filepath.Join(hashDir, filepath.Base(executableFile)+".java")
		err = util.CopyFile(deployExecutableFileBIN, hashExecutableFileBIN)
		if err != nil {
			log.Errorf("generateBuildFile copy binary file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, deployExecutableFileBIN, hashExecutableFileBIN, err)
			return "", err
		}
		err = util.CopyFile(deployExecutableFileABI, hashExecutableFileABI)
		if err != nil {
			log.Errorf("generateBuildFile copy binary file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, deployExecutableFileABI, hashExecutableFileABI, err)
			return "", err
		}
		err = util.CopyFile(deployExecutableFileJAVA, hashExecutableFileJAVA)
		if err != nil {
			log.Errorf("generateBuildFile copy binary file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, deployExecutableFileJAVA, hashExecutableFileJAVA, err)
			return "", err
		}
		//copy compress file
		source7z := filepath.Join(buildDirectory, fileName7z)
		target7z := filepath.Join(hashDir, fileName7z)
		err = util.CopyFile(source7z, target7z)
		if err != nil {
			log.Errorf("generateBuildFile copy compress file fail. "+
				"uid:%s, source:%s, target:%s, err :%s", uid, source7z, target7z, err)
			return "", err
		}
		// 保存 build信息到build-info表格
		compileInfo := generateBuildInfoNew(uid, curDirectory, file7z, nameNoExt, md5SumHex, sourceCodeMd5SumHex)
		saveErr := conf.SaveCompileInfo(compileInfo)
		if saveErr != nil {
			log.Errorf("")
			return "", saveErr
		}

		//deploy
		//./cmc client contract user create \
		//--contract-name=balance001 \
		//--runtime-type=EVM \
		//--byte-code-path=./testdata/balance-evm-demo/ledger_balance.bin \
		//--abi-file-path=./testdata/balance-evm-demo/ledger_balance.abi \
		//--version=1.0 \
		//--sdk-conf-path=./testdata/sdk_config.yml \
		//--admin-key-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key,./testdata/crypto-config/wx-org2.chainmaker.org/user/admin1/admin1.sign.key,./testdata/crypto-config/wx-org3.chainmaker.org/user/admin1/admin1.sign.key \
		//--admin-crt-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt,./testdata/crypto-config/wx-org2.chainmaker.org/user/admin1/admin1.sign.crt,./testdata/crypto-config/wx-org3.chainmaker.org/user/admin1/admin1.sign.crt \
		//--sync-result=true
		goos := strings.Split(platform, "_")[0]
		goarch := strings.Split(platform, "_")[1]

		var goBuildArgs []string
		goBuildArgs = append(goBuildArgs, "client")
		goBuildArgs = append(goBuildArgs, "contract")
		goBuildArgs = append(goBuildArgs, "user")
		goBuildArgs = append(goBuildArgs, "create")
		goBuildArgs = append(goBuildArgs, "--contract-name="+contractName)
		goBuildArgs = append(goBuildArgs, "--version="+version)
		goBuildArgs = append(goBuildArgs, "--sdk-conf-path="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/sdk_config.yml")
		goBuildArgs = append(goBuildArgs, "--byte-code-path="+deployExecutableFileBIN)
		goBuildArgs = append(goBuildArgs, "--abi-file-path="+deployExecutableFileABI)
		goBuildArgs = append(goBuildArgs, "--runtime-type=EVM")
		goBuildArgs = append(goBuildArgs, "--admin-crt-file-paths="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt")
		goBuildArgs = append(goBuildArgs, "--admin-key-file-paths="+runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/"+chaiId+"/testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key")
		goBuildArgs = append(goBuildArgs, "--sync-result=true")
		if params != "" {
			goBuildArgs = append(goBuildArgs, "--params=\""+params+"\"")
		}

		cmd := exec.Command(runtime.GOROOT()+RealSdkGoRootSuffix+"/bin/cmc", goBuildArgs...)
		cmd.Dir = curDirectory
		//非测试环境执行环境变量设置
		if global.TestnetEnv != true {
			setCmdEnvWithOsAndArchAndGoRoot(cmd, uid, goos, goarch, os.Getenv("GOPATH"), runtime.GOROOT()+RealSdkGoRootSuffix)
		}

		stdout, stderr, err := util.OpenStdOutAndStdErr(cmd)
		if err != nil {
			log.Errorf("CrossCompilationHandler open stdout and stderr failed. err:%s", err)
			return nil, nil
		}

		user := conf.GetUser(uid)

		err = writeMessageToWebSocket(sid, uid, "deploy", "正在发布合约...")
		if err != nil {
			log.Errorf("deploy write start build message to websocket failed.uid:%s, err :%s", uid, err)
			return nil, nil
		}

		if err := cmd.Start(); nil != err {
			log.Errorf("deploy start cmd faild. err:%s", err)
			return nil, nil
		}
		log.Debugf("cmd info: path %v,args: %v,env: %v,dir: %v ", cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
		WaitCmdRunSuccessEVM(rand.Int(), cmd, stdout, stderr, user.Locale, executableFile, nameNoExt, curDirectory, sid)

		return file7z, nil
	})
	return doRet.(string), doRetErr
}

func generateBuildInfoNew(uid, srcPath, path7z, contractName, md5sum, SourceCodeHash string) *conf.CompileInfoModel {
	result := conf.CompileInfoModel{
		UserId:       uid,
		ContractName: contractName,
		SrcMd5:       SourceCodeHash,
		BinMd5:       md5sum,
		BuildTime:    time.Now().Unix(),
		Path:         path7z,
		Methods:      getMethodFromPath(srcPath),
	}
	return &result
}

// func generateBuildInfo(path, contractName, md5sum, SourceCodeHash string) *buildInfo {
// 	result := buildInfo{
// 		ContractName:   contractName,
// 		Date:           time.Now().Format(common.TimeLayout),
// 		Hash:           md5sum,
// 		Methods:        getMethodFromPath(path),
// 		SourceCodeHash: SourceCodeHash,
// 	}
// 	return &result
// }

func getMethodFromPath(path string) []string {
	methods, err := session.GetMethodsFormPath(path)
	if err != nil {
		log.Warnf("get method fail. path:%s", path)
		return make([]string, 0)
	}
	return methods
}

func convertString2SliceString(input string) string {
	// 解析输入的json字符串
	var m map[string]string
	err := json.Unmarshal([]byte(input), &m)
	if err != nil {
		fmt.Println("解析失败:", err)
		return ""
	}
	// 将map转换成slice
	var result []map[string]string
	for k, v := range m {
		temp := make(map[string]string)
		temp[k] = v
		result = append(result, temp)
	}
	// 将结果转换成json字符串
	output, err := json.Marshal(result)
	if err != nil {
		fmt.Println("转换失败:", err)
		return ""
	}
	log.Errorf("evm build -----hhhhh. curDirectory:%s", string(output))

	return string(output)
}
